package com.string.pokergame.client;

import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.Socket;
import java.net.SocketException;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Timer;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import static com.string.pokergame.client.CardUtil.*;

/**
 * 三人斗地主游戏的客户端
 *
 * @author String
 */
public class GameClient extends JPanel {
    private static final long serialVersionUID = 1L;

    public static final int WIDTH = 800;
    public static final int HEIGHT = 500;
    public static int width = 70, height = 100;
    public static final int SHOW_TIME = 30;
    public static final int ROB_TIME = 15;

    public static final int START = 0;
    public static final int WAIT = 1;
    public static final int SELECT_ROOM = 2;
    public static final int IN_ROOM = 3;
    public static final int GAME = 4;
    public static final int OVER = 5;

    public static final int BOMB = 6;
    public static final int KINGBOMB = 9;

    public static BufferedImage background;
    public static BufferedImage[] card = new BufferedImage[54];
    public static BufferedImage start;
    public static BufferedImage farmer;
    public static BufferedImage lord;
    public static BufferedImage login;
    public static BufferedImage title;
    public static BufferedImage button1;
    public static BufferedImage button2;
    public static BufferedImage show;
    public static BufferedImage tip;
    public static BufferedImage wait;
    public static BufferedImage join;
    public static BufferedImage create;
    public static BufferedImage readyP;
    public static BufferedImage noReady;
    public static BufferedImage exit;
    public static BufferedImage cardBack;
    public static BufferedImage pass;
    public static BufferedImage rob;
    public static BufferedImage noRob;
    public static BufferedImage timer;
    public static BufferedImage goOn;
    public static BufferedImage lordCard;
    public static BufferedImage leave;
    public static BufferedImage tips1;
    public static BufferedImage tips2;
    public static BufferedImage tips3;
    public static BufferedImage auto;
    public static BufferedImage cancelAuto;
    public static BufferedImage noteCard;

    public static int state = START;
    public static volatile boolean toDo = false, toRob = false, isLord = false;
    public static boolean isPass = false, isWin = false, key = false;
    public static volatile int isRob = 0, times = 0, errTips = 0;
    public static int score = 0, point = 0, tipsId = 0;
    public static volatile boolean robIsOver = false, showPass = false, toPass = false;

    static { // 加载背景图和文字图片资源
        try {
            noteCard = ImageIO.read(Objects.requireNonNull(GameClient.class.getResource("image/jipaiqi.png")));
            auto = ImageIO.read(Objects.requireNonNull(GameClient.class.getResource("image/tuoguan.png")));
            cancelAuto = ImageIO.read(Objects.requireNonNull(GameClient.class.getResource("image/qxtg.png")));
            noReady = ImageIO.read(Objects.requireNonNull(GameClient.class.getResource("image/cancelReady.png")));
            tips1 = ImageIO.read(Objects.requireNonNull(GameClient.class.getResource("image/pxx.png")));
            tips2 = ImageIO.read(Objects.requireNonNull(GameClient.class.getResource("image/pxcw.png")));
            tips3 = ImageIO.read(Objects.requireNonNull(GameClient.class.getResource("image/mdp.png")));
            leave = ImageIO.read(Objects.requireNonNull(GameClient.class.getResource("image/lixian.png")));
            goOn = ImageIO.read(Objects.requireNonNull(GameClient.class.getResource("image/jixu.png")));
            lordCard = ImageIO.read(Objects.requireNonNull(GameClient.class.getResource("image/dzp.png")));
            timer = ImageIO.read(Objects.requireNonNull(GameClient.class.getResource("image/naozhong.png")));
            noRob = ImageIO.read(Objects.requireNonNull(GameClient.class.getResource("image/bq.png")));
            rob = ImageIO.read(Objects.requireNonNull(GameClient.class.getResource("image/qdz.png")));
            pass = ImageIO.read(Objects.requireNonNull(GameClient.class.getResource("image/bc.png")));
            cardBack = ImageIO.read(Objects.requireNonNull(GameClient.class.getResource("image/paishu.png")));
            exit = ImageIO.read(Objects.requireNonNull(GameClient.class.getResource("image/likai.png")));
            readyP = ImageIO.read(Objects.requireNonNull(GameClient.class.getResource("image/zb.png")));
            join = ImageIO.read(Objects.requireNonNull(GameClient.class.getResource("image/jrfj.png")));
            create = ImageIO.read(Objects.requireNonNull(GameClient.class.getResource("image/cjfj.png")));
            wait = ImageIO.read(Objects.requireNonNull(GameClient.class.getResource("image/wait.jpg")));
            tip = ImageIO.read(Objects.requireNonNull(GameClient.class.getResource("image/tishi.png")));
            show = ImageIO.read(Objects.requireNonNull(GameClient.class.getResource("image/showCards.png")));
            start = ImageIO.read(Objects.requireNonNull(GameClient.class.getResource("image/ksyx.png")));
            button1 = ImageIO.read(Objects.requireNonNull(GameClient.class.getResource("image/g.png")));
            button2 = ImageIO.read(Objects.requireNonNull(GameClient.class.getResource("image/g2.png")));
            login = ImageIO.read(Objects.requireNonNull(GameClient.class.getResource("image/login.jpg")));
            title = ImageIO.read(Objects.requireNonNull(GameClient.class.getResource("image/nmddz.png")));
            background = ImageIO.read(Objects.requireNonNull(GameClient.class.getResource("image/background.jpg")));
            farmer = ImageIO.read(Objects.requireNonNull(GameClient.class.getResource("image/farmer.png")));
            lord = ImageIO.read(Objects.requireNonNull(GameClient.class.getResource("image/lord.png")));
            for (int i = 0; i < 54; i++) {
                card[i] = ImageIO.read(Objects.requireNonNull(GameClient.class.getResource("image/" + (i + 1) + ".jpg")));
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static Card[] totalCards = new Card[54];
    public static Card[] lordCards = new Card[0];
    public static Card[] nowCards = null; // 当前在桌面上的上家的牌
    public static volatile Card[] myCards = new Card[0];
    public static volatile Card[] showCards = new Card[0];
    public static int[] noteCards = new int[20];
    public static int[] tipsIndex = new int[0];
    public static Button startB, showB, putDownB, joinB, createB, exitB, readyB, passB;
    public static Button robB, noRobB, noReadyB, goOnB, exitRoomB;
    public static Button autoB, cancelAutoB;
    public static TimerTik timeTik1, timeTik2, timeTik3;
    public Socket socket = null;
    public OutputStream serverOut;
    public OutputStreamWriter serverOutWriter;
    public static PrintWriter serverPrinter = null;
    public InputStream serverInput;
    public InputStreamReader serverInputReader;
    public static BufferedReader serverReader = null;
    public int roomNum = 0, myId = -1;
    public static volatile int cardType = 0;
    public String name, tmpMsg;
    public static JFrame frame;
    public static Font f;
    public static List<int[]> tips = new ArrayList<>();
    /**
     * 左边的玩家对象
     */
    public static Player pl = null;
    /**
     * 右边的玩家对象
     */
    public static Player pr = null;
    public static volatile int nowLen = 0;
    public static volatile int nowCardType = 0;
    public static GameClient game = new GameClient();
    ExecutorService exec = Executors.newFixedThreadPool(30);
    private ServerHandler gameHandler = null;

    public GameClient() {
        // 初始化各种控件
        cancelAutoB = new Button(340, 295, 100, 50);
        autoB = new Button(520, 305, 80, 30);
        timeTik1 = new TimerTik(100, 150); // 左家的计时器
        timeTik2 = new TimerTik(630, 150); // 右家的计时器
        timeTik3 = new TimerTik(375, 250); // 自己的计时器
        goOnB = new Button(237, 300, 100, 50);
        exitRoomB = new Button(450, 300, 100, 50);
        noReadyB = new Button(350, 400, 100, 50);
        readyB = new Button(237, 400, 100, 50);
        exitB = new Button(450, 400, 100, 50);
        joinB = new Button(150, 200, 200, 100);
        createB = new Button(450, 200, 200, 100);
        putDownB = new Button(430, 305, 80, 30);
        passB = new Button(340, 305, 80, 30);
        startB = new Button(550, 350, button1.getWidth(), button1.getHeight());
        showB = new Button(250, 305, 80, 30);
        robB = new Button(250, 305, 80, 30);
        noRobB = new Button(430, 305, 80, 30);
        // 初始化总卡组
        Arrays.fill(noteCards, 4);
        int indexNum = 3;
        for (int i = 0; i < 52; i++) {
            totalCards[i] = new Card();
            totalCards[i].image = card[i + 2];
            totalCards[i].num = indexNum;
            indexNum++;
            if (indexNum == 15) {
                indexNum = 16;
            }
            if (indexNum == 17) {
                indexNum = 3;
            }
        }
        // 小王
        totalCards[52] = new Card();
        totalCards[52].image = card[1];
        totalCards[52].num = 18;
        noteCards[18] = 1;
        // 大王
        totalCards[53] = new Card();
        totalCards[53].image = card[0];
        totalCards[53].num = 19;
        noteCards[19] = 1;
    }

    /**
     * 初始化游戏内的属性数据
     */
    public void newData() {
        toPass = false;
        times = 0;
        robIsOver = false;
        isWin = false;
        if (pl != null) {
            pl.isWin = false;
            pl.isLord = false;
            pl.isRob = 0;
            pl.isPass = true;
            pl.isDo = false;
            pl.cardsNum = 0;
        }
        if (pr != null) {
            pr.isWin = false;
            pr.isLord = false;
            pr.isRob = 0;
            pr.isPass = true;
            pr.isDo = false;
            pr.cardsNum = 0;
        }
        isLord = false;
        isRob = 0;
        lordCards = new Card[0];
        nowCardType = 0;
        nowLen = 0;
        nowCards = null;
    }

    public void stopAndRestart() {
        state = START;
        newData();
        pl = null;
        pr = null;
        stopSocket();
        if (gameHandler != null) {
            gameHandler.exit();
        }
        JOptionPane.showMessageDialog(null, "失去连接!", "服务器连接失败", JOptionPane.ERROR_MESSAGE);
    }

    public void stopSocket() {
        if (socket != null) {
            try {
                socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 将选择的牌缩回
     */
    public static void clearChoose() {
        for (Card myCard : myCards) {
            if (myCard.y == 330) {
                myCard.y = 350;
            }
        }
    }

    /**
     * 拿牌
     *
     * @throws Exception
     */
    public void getCards() throws Exception {
        myCards = new Card[0];
        int index = 0;
        for (int i = 0; i < 17; i++) {
            // 从客户端接收牌的总卡组下标
            index = Integer.parseInt(serverReader.readLine());
            myCards = Arrays.copyOf(myCards, myCards.length + 1);
            myCards[i] = new Card(250 + i * 15, 350);
            myCards[i].image = totalCards[index].image;
            myCards[i].num = totalCards[index].num;
            noteCards[myCards[i].num]--;
            myCards[i].cardIndex = index;
            pl.cardsNum++;
            pr.cardsNum++;
        }
        // 向服务器发送接牌结束信号
        serverPrinter.println("OVER");
        // 接收地主牌
        for (int i = 0; i < 3; i++) {
            lordCards = Arrays.copyOf(lordCards, lordCards.length + 1);
            lordCards[i] = new Card(280 + 80 * i, 30);
            index = Integer.parseInt(serverReader.readLine());
            lordCards[i].image = totalCards[index].image;
            lordCards[i].num = totalCards[index].num;
            lordCards[i].cardIndex = index;
        }
    }

    /**
     * 提出已选择的牌
     */
    public static void chooseCard() {
        showCards = new Card[0];
        for (Card myCard : myCards) {
            if (myCard.y == 330) {
                showCards = Arrays.copyOf(showCards, showCards.length + 1);
                showCards[showCards.length - 1] = new Card();
                showCards[showCards.length - 1].image = myCard.image;
                showCards[showCards.length - 1].num = myCard.num;
                showCards[showCards.length - 1].cardIndex = myCard.cardIndex;
            }
        }
    }

    /**
     * 将选好的牌发送出去
     */
    public static void putMyCards() {
        int len;
        // 将要打出的牌从手牌中删除
        for (int i = 0; i < myCards.length; i++) {
            if (myCards[i].y == 330) {
                swapCards(myCards[i], myCards[myCards.length - 1]);
                myCards = Arrays.copyOf(myCards, myCards.length - 1);
                i--;
            }
        }
        // 排序手中的卡牌
        cardSort(myCards);
        len = showCards.length;
        if (myCards.length == 0) {
            len++;
            showCards = Arrays.copyOf(showCards, showCards.length + 1);
            showCards[showCards.length - 1] = new Card();
            showCards[showCards.length - 1].cardIndex = -1;
            state = OVER;
            isWin = true;
            score();
            pl.ready = 0;
            pr.ready = 0;
        }
        // 发送要出的卡牌的总卡组下标给服务器
        serverPrinter.println("SHOW");
        serverPrinter.println(len);
        serverPrinter.println(cardType);
        for (Card showCard : showCards) {
            serverPrinter.println(showCard.cardIndex);
        }
        // 将要出的卡组的x,y坐标算出来
        int x = 400 - showCards.length * 15 / 2 - 50;
        int y = 200;
        for (int i = 0; i < showCards.length; i++) {
            showCards[i].x = x + 15 * i;
            showCards[i].y = y;
        }
        timeTik3.flag = false;
        nowCardType = 0;
        nowCards = null;
        nowLen = 0;
        errTips = 0;
        toDo = false;
    }

    /**
     * 递归方法找出大于上家的牌
     *
     * @param index   当前的tipsIndex的下标
     * @param myIndex 当前的myCards的下标
     */
    public static void findTips(int index, int myIndex) {
        if (index > myCards.length || myIndex > myCards.length) {
            return;
        }
        if (nowLen == 0) {
            return;
        }
        if (nowLen >= 4 && index > nowLen) {
            return;
        }
        if (nowLen < 4 && index > 4) {
            return;
        }
        if (nowCards == null || nowCards.length == 0) {
            return;
        }
        Card[] tip;
        int cardType;
        for (int i = myCards.length - 1; i >= myIndex; i--) {
            tipsIndex = Arrays.copyOf(tipsIndex, index + 1);
            tipsIndex[index] = i;
            tip = new Card[0];
            for (int k : tipsIndex) {
                tip = Arrays.copyOf(tip, tip.length + 1);
                tip[tip.length - 1] = new Card();
                tip[tip.length - 1].num = myCards[k].num;
            }
            cardType = checkCards(tip);
            if (cardType == nowCardType && tip.length == nowLen && tip[0].num > nowCards[0].num) {
                tips.add(tipsIndex);
            } else if ((cardType == BOMB && nowCardType != BOMB && nowCardType != KINGBOMB) || cardType == KINGBOMB) {
                tips.add(tipsIndex);
            }
            findTips(index + 1, i + 1);
        }
    }

    /**
     * 在集合中循环遍历每个提示,将提示的牌的y坐标-20.
     */
    public static void showTips() {
        if (tipsId > tips.size() - 1) {
            tipsId = 0;
        }
        clearChoose();
        if (tips.size() == 0) {
            return;
        }
        int[] arr = tips.get(tipsId);
        for (int j : arr) {
            myCards[j].y -= 20;
        }
        tipsId++;
    }

    public synchronized static void autoPass() {
        if (toDo && showPass) {
            serverPrinter.println("PASS");
            serverPrinter.println(nowLen);
            serverPrinter.println(nowCardType);
            toDo = false;
            isPass = true;
            timeTik3.flag = false;
            errTips = 0;
            clearChoose();
        } else if (toRob) {
            serverPrinter.println("N");
            isRob = 1;
            toRob = false;
            timeTik3.flag = false;
        } else if (toDo) {
            clearChoose();
            myCards[myCards.length - 1].y -= 20;
            chooseCard();
            if (showCards.length != 0) {
                cardType = checkCards(showCards);
            } else {
                cardType = 0;
            }
            putMyCards();
        }
    }

    public static void score() {
        if (pl.isWin) {
            if (isLord) {
                pl.score += point / 2;
                pr.score += point / 2;
                score -= point;
            } else if (pl.isLord) {
                pl.score += point;
                pr.score -= point / 2;
                score -= point / 2;
            } else {
                pl.score += point / 2;
                pr.score -= point;
                score += point / 2;
            }
        }
        if (pr.isWin) {
            if (isLord) {
                pl.score += point / 2;
                pr.score += point / 2;
                score -= point;
            } else if (pr.isLord) {
                pl.score -= point / 2;
                pr.score += point;
                score -= point / 2;
            } else {
                pl.score -= point;
                pr.score += point / 2;
                score += point / 2;
            }
        }
        if (isWin) {
            if (isLord) {
                pl.score -= point / 2;
                pr.score -= point / 2;
                score += point;
            } else if (pr.isLord) {
                pl.score += point / 2;
                pr.score -= point;
                score += point / 2;
            } else {
                pl.score -= point;
                pr.score += point / 2;
                score += point / 2;
            }
        }
    }

    public void paintNoteCards(Graphics g) {
        f = new Font(null, 0, 15);
        g.setFont(f);
        g.drawString(String.valueOf(noteCards[19]), 32, 50);
        g.drawString(String.valueOf(noteCards[18]), 50, 50);
        int step = 0;
        for (int i = 16; i > 2; i--) {
            if (i != 15) {
                g.drawString(String.valueOf(noteCards[i]), 67 + step * 16, 50);
                step++;
            }
        }
    }

    public void paintButton(Button butt, Graphics g) {
        g.drawImage(butt.image, butt.getX(), butt.getY(), butt.getWidth(), butt.getHeight(), null);
    }

    public void paintCards(Graphics g) {
        // 打印三张地主牌
        if (lordCards != null) {
            if (robIsOver) {
                for (Card value : lordCards) {
                    g.drawImage(value.image, value.x, value.y, width, height, null);
                    g.drawImage(lordCard, value.x, value.y, width, height, null);
                }
            } else {
                for (Card value : lordCards) {
                    g.drawImage(cardBack, value.x, value.y, width, height, null);
                    g.drawImage(lordCard, value.x, value.y, width, height, null);
                }
            }
        }
        // 打印自己的手牌
        for (Card myCard : myCards) {
            g.drawImage(myCard.image, myCard.x, myCard.y, width, height, null);
        }
        // 打印自己出的牌
        for (Card showCard : showCards) {
            g.drawImage(showCard.image, showCard.x, showCard.y, width, height, null);
        }
        // 打印左家出的牌
        if (pl != null) {
            for (int i = 0; i < pl.cards.length; i++) {
                g.drawImage(pl.cards[i].image, pl.cards[i].x, pl.cards[i].y, width, height, null);
            }
        }
        // 打印右家出的牌
        if (pr != null) {
            for (int i = 0; i < pr.cards.length; i++) {
                g.drawImage(pr.cards[i].image, pr.cards[i].x, pr.cards[i].y, width, height, null);
            }
        }
    }

    @Override
    public void paint(Graphics g) {
        g.drawImage(background, 0, 0, frame.getWidth(), frame.getHeight(), null);
        // 游戏开始状态的界面图:开始画面,开始按钮
        f = new Font(null, Font.BOLD, 20);
        if (state == START) {
            g.drawImage(login, 0, 0, frame.getWidth(), frame.getHeight(), null);
            g.drawImage(title, 50, 30, 200, 200, null);
            paintButton(startB, g);
            g.drawImage(start, 575, 370, null);
        } // 游戏大厅状态的画面打印
        else if (state == SELECT_ROOM) {
            paintButton(joinB, g);
            g.drawImage(join, joinB.getX() + 25, joinB.getY() + 20, joinB.getWidth() - 50, joinB.getHeight() - 50,
                    null);
            paintButton(createB, g);
            g.drawImage(create, createB.getX() + 25, createB.getY() + 20, createB.getWidth() - 50,
                    createB.getHeight() - 50, null);
        } // 房间内的画面打印
        else if (state == IN_ROOM) {
            paintButton(exitB, g);
            g.drawImage(exit, exitB.getX(), exitB.getY(), exitB.getWidth(), exitB.getHeight(), null);
            paintButton(readyB, g);
            g.drawImage(start, readyB.getX() + 10, readyB.getY() + 8, readyB.getWidth() - 20, readyB.getHeight() - 20,
                    null);
            g.setFont(f);
            if (pl != null) {
                g.drawString(pl.name, 30, 120);
                if (pl.ready == 1) {
                    g.drawImage(readyP, 30, 150, null);
                }
            }
            if (pr != null) {
                g.drawString(pr.name, 700, 120);
                if (pr.ready == 1) {
                    g.drawImage(readyP, 700, 150, null);
                }
            }
            g.drawString(name, 150, 450);
        } // 准备状态下的 画面打印
        else if (state == WAIT) {
            g.drawImage(readyP, 375, 300, null);
            g.setFont(f);
            if (pl != null) {
                g.drawString(pl.name, 30, 120);
                if (pl.ready == 1) {
                    g.drawImage(readyP, 30, 150, null);
                }
            }
            if (pr != null) {
                g.drawString(pr.name, 700, 120);
                if (pr.ready == 1) {
                    g.drawImage(readyP, 700, 150, null);
                }
            }
            g.drawString(name, 150, 450);
            paintButton(noReadyB, g);
            g.drawImage(noReady, noReadyB.getX(), noReadyB.getY(), noReadyB.getWidth(), noReadyB.getHeight(), null);
        } // 游戏状态打印
        else if (state == GAME) {
            if (pl != null) {
                g.setFont(f);
                g.drawString(pl.name, 30, 250);
                g.drawString("Score:" + pl.score, 30, 275);
                if (pl.cardsNum != 0) {
                    g.drawImage(cardBack, 30, 150, null);
                }
                g.setFont(f);
                g.drawString(String.valueOf(pl.cardsNum), 30, 190);
                if (pl.isDo) {
                    g.drawImage(timeTik1.image, timeTik1.x, timeTik1.y, 50, 50, null);
                }
                if (pl.isRob == 1 && !robIsOver) {
                    g.drawImage(noRob, 100, 150, null);
                } else if (pl.isRob == 2 && !robIsOver) {
                    g.drawImage(rob, 100, 150, null);
                }
                if (pl.isPass && robIsOver) {
                    g.drawImage(pass, 100, 150, null);
                }
                if (pl.isLord && robIsOver) {
                    g.drawImage(lord, 15, 35, null);
                } else if (robIsOver) {
                    g.drawImage(farmer, 15, 35, null);
                }
            } else {
                g.drawImage(cardBack, 30, 150, null);
                g.drawImage(leave, 30, 150, null);
            }
            if (pr != null) {
                g.setFont(f);
                g.drawString(pr.name, 700, 250);
                g.drawString("Score:" + pr.score, 700, 275);
                g.setFont(f);
                if (pr.cardsNum != 0) {
                    g.drawImage(cardBack, 700, 150, null);
                }
                g.drawString(String.valueOf(pr.cardsNum), 700, 190);
                if (pr.isDo) {
                    g.drawImage(timeTik2.image, timeTik2.x, timeTik2.y, 50, 50, null);
                }
                if (pr.isRob == 1 && !robIsOver) {
                    g.drawImage(noRob, 600, 150, null);
                } else if (pr.isRob == 2 && !robIsOver) {
                    g.drawImage(rob, 600, 150, null);
                }
                if (pr.isPass && robIsOver) {
                    g.drawImage(pass, 600, 150, null);
                }
                if (pr.isLord && robIsOver) {
                    g.drawImage(lord, 675, 35, null);
                } else if (robIsOver) {
                    g.drawImage(farmer, 675, 35, null);
                }
            } else {
                g.drawImage(cardBack, 700, 150, null);
                g.drawImage(leave, 700, 150, null);
            }
            g.drawString(name, 625, 400);
            g.drawString("Score:" + score, 625, 435);
            paintCards(g);
            if (isRob == 1 && !robIsOver) {
                g.drawImage(noRob, 350, 300, null);
            } else if (isRob == 2 && !robIsOver) {
                g.drawImage(rob, 350, 300, null);
            }
            if (isPass && robIsOver) {
                g.drawImage(pass, 350, 300, null);
            }
            if (isLord && robIsOver) {
                g.drawImage(lord, 150, 350, 100, 100, null);
            } else if (robIsOver) {
                g.drawImage(farmer, 150, 350, 100, 100, null);
            }
            if (toPass) {
                g.drawImage(cancelAutoB.image, cancelAutoB.getX(), cancelAutoB.getY(), cancelAutoB.getWidth(),
                        cancelAutoB.getHeight(), null);
                g.drawImage(cancelAuto, cancelAutoB.getX() + 10, cancelAutoB.getY() + 5, cancelAutoB.getWidth() - 20,
                        cancelAutoB.getHeight() - 20, null);
            }
            if (toRob) {
                g.drawImage(autoB.image, autoB.getX(), autoB.getY(), autoB.getWidth(), autoB.getHeight(), null);
                g.drawImage(auto, autoB.getX() + 5, autoB.getY() + 3, autoB.getWidth() - 10, autoB.getHeight() - 10,
                        null);
                g.drawImage(timer, 375, 250, 50, 50, null);
                g.drawImage(robB.image, robB.getX(), robB.getY(), robB.getWidth(), robB.getHeight(), null);
                g.drawImage(rob, robB.getX() + 5, robB.getY() + 3, robB.getWidth() - 10, robB.getHeight() - 10, null);
                g.drawImage(noRobB.image, noRobB.getX(), noRobB.getY(), noRobB.getWidth(), noRobB.getHeight(), null);
                g.drawImage(noRob, noRobB.getX() + 5, noRobB.getY() + 3, noRobB.getWidth() - 10,
                        noRobB.getHeight() - 10, null);
            }
            if (toDo) {
                g.drawImage(autoB.image, autoB.getX(), autoB.getY(), autoB.getWidth(), autoB.getHeight(), null);
                g.drawImage(auto, autoB.getX() + 5, autoB.getY() + 3, autoB.getWidth() - 10, autoB.getHeight() - 10,
                        null);
                g.drawImage(timeTik3.image, timeTik3.x, timeTik3.y, 50, 50, null);
                g.drawImage(showB.image, showB.getX(), showB.getY(), showB.getWidth(), showB.getHeight(), null);
                g.drawImage(show, showB.getX() + 5, showB.getY() + 3, showB.getWidth() - 10, showB.getHeight() - 10,
                        null);
                if (showPass) {
                    g.drawImage(passB.image, passB.getX(), passB.getY(), passB.getWidth(), passB.getHeight(), null);
                    g.drawImage(pass, passB.getX() + 5, passB.getY() + 3, passB.getWidth() - 10, passB.getHeight() - 10,
                            null);
                }
                g.drawImage(putDownB.image, putDownB.getX(), putDownB.getY(), putDownB.getWidth(), putDownB.getHeight(),
                        null);
                g.drawImage(tip, putDownB.getX() + 5, putDownB.getY() + 3, putDownB.getWidth() - 10,
                        putDownB.getHeight() - 10, null);
                if (errTips == 1) {
                    g.drawImage(tips1, 200, 175, null);
                } else if (errTips == 2) {
                    g.drawImage(tips2, 200, 175, null);
                } else if (errTips == 3) {
                    g.drawImage(tips3, 200, 175, null);
                }
            }
            f = new Font(null, 0, 10);
            g.setFont(f);
            g.drawString("本局分数:" + point, 350, 20);
            // 打印记牌器:
            if (key) {
                g.drawImage(noteCard, 10, 10, 260, 50, null);
                paintNoteCards(g);
            }
        } // 游戏结束状态打印
        else if (state == OVER) {
            g.drawString(name, 125, 400);
            g.drawString("Score:" + score, 125, 435);
            paintCards(g);
            if (pl != null) {
                g.setFont(f);
                g.drawString(pl.name, 30, 120);
                g.drawString("Score:" + pl.score, 30, 145);
                g.drawImage(cardBack, 30, 150, null);
                g.setFont(f);
                g.drawString(String.valueOf(pl.cardsNum), 30, 190);
                if (pl.isWin) {
                    if (isLord) {
                        g.drawString("You are a Lord,You Lose!", 175, 225);
                    } else if (pl.isLord) {
                        g.drawString("You are a Farmer,You Lose!", 175, 225);
                    } else {
                        g.drawString("You are a Farmer,You Win!", 175, 225);
                    }
                }
            }
            if (pr != null) {
                g.setFont(f);
                g.drawString(pr.name, 700, 120);
                g.drawString("Score:" + pr.score, 700, 145);
                g.setFont(f);
                g.drawImage(cardBack, 700, 150, null);
                g.drawString(String.valueOf(pr.cardsNum), 700, 190);
                if (pr.isWin) {
                    if (isLord) {
                        g.drawString("You are a Lord,You Lose!", 175, 225);
                    } else if (pr.isLord) {
                        g.drawString("You are a Farmer,You Lose!", 175, 225);
                    } else {
                        g.drawString("You are a Farmer,You Win!", 175, 225);
                    }
                }
            }
            if (isWin) {
                g.setFont(f);
                g.drawString("Your WIN!", 350, 225);
            }
            g.drawImage(goOnB.image, goOnB.getX(), goOnB.getY(), goOnB.getWidth(), goOnB.getHeight(), null);
            g.drawImage(goOn, goOnB.getX(), goOnB.getY(), goOnB.getWidth(), goOnB.getHeight(), null);
            g.drawImage(exitRoomB.image, exitRoomB.getX(), exitRoomB.getY(), exitRoomB.getWidth(),
                    exitRoomB.getHeight(), null);
            g.drawImage(exit, exitRoomB.getX(), exitRoomB.getY(), exitRoomB.getWidth(), exitRoomB.getHeight(), null);
        }
    }

    /**
     * 游戏主方法
     */
    public void action() {
        Timer t = new Timer();
        t.schedule(new TimerTask() {
            @Override
            public void run() {
                repaint();
            }
        }, 0, 5);

        MouseAdapter m = new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                // 退出按钮
                if (buttonFlash(e, state == IN_ROOM, exitB)) {
                    serverPrinter.println("EXIT");
                    newData();
                    pl = null;
                    pr = null;
                    score = 0;
                    state = SELECT_ROOM;
                    frame.setTitle("局域网斗地主:" + name);
                }
                // 取消准备按钮
                if (buttonFlash(e, state == WAIT, noReadyB)) {
                    state = IN_ROOM;
                    try {
                        tmpMsg = serverReader.readLine();
                        if ("ALIVE".equals(tmpMsg)) {
                            serverPrinter.println("NOREADY");
                        }
                    } catch (IOException e1) {
                        e1.printStackTrace();
                    }
                }
                // 准备按钮
                if (buttonFlash(e, state == IN_ROOM, readyB)) {
                    System.out.println("READY");
                    serverPrinter.println("READY");
                    state = WAIT;
                }
                // 继续游戏按钮
                if (buttonFlash(e, state == OVER, goOnB)) {
                    serverPrinter.println("CONTINUE");
                    if (pl != null) {
                        pl.cards = new Card[0];
                    }
                    if (pr != null) {
                        pr.cards = new Card[0];
                    }
                    lordCards = new Card[0];
                    myCards = new Card[0];
                    showCards = new Card[0];
                    isRob = 0;
                    isPass = false;
                    toDo = false;
                    toRob = false;
                    isLord = false;
                    state = IN_ROOM;
                }
                // 退出房间按钮
                if (buttonFlash(e, state == OVER, exitRoomB)) {
                    serverPrinter.println("EXIT");
                    newData();
                    score = 0;
                    pl = null;
                    pr = null;
                    state = SELECT_ROOM;
                    frame.setTitle("局域网斗地主:" + name);
                }
                // 开始游戏按钮
                if (buttonFlash(e, state == START, startB)) {
                    try {
                        String ip = JOptionPane.showInputDialog("请输入服务器的IP地址(直接点击确定则以默认IP:127.0.0.1连接):");
                        if ("".equals(ip)) {
                            ip = "127.0.0.1";
                        }
                        if (ip != null) {
                            socket = new Socket(ip, 3000);
                            // 创建服务器输出流
                            serverOut = socket.getOutputStream();
                            serverOutWriter = new OutputStreamWriter(serverOut, StandardCharsets.UTF_8);
                            serverPrinter = new PrintWriter(serverOutWriter, true);
                            // 创建服务器输入流
                            serverInput = socket.getInputStream();
                            serverInputReader = new InputStreamReader(serverInput, StandardCharsets.UTF_8);
                            serverReader = new BufferedReader(serverInputReader);
                            // 从用户处输入客户端名字
                            name = JOptionPane.showInputDialog("服务器连接成功!请输入你的游戏昵称:");
                            // 将名字传给服务器
                            serverPrinter.println(name);
                            // 接收从服务端发来的名字不合法或者重复的信息
                            while ("N".equals(serverReader.readLine())) {
                                name = JOptionPane.showInputDialog("你所输入的昵称不合法或者已存在,请重新输入你的名字:");
                                serverPrinter.println(name);
                            }
                            frame.setTitle("局域网斗地主:" + name);
                            state = SELECT_ROOM;
                            // 开启服务器监听线程
                            gameHandler = new ServerHandler();
                            gameHandler.start();
                        }
                    } catch (Exception e1) {
                        e1.printStackTrace();
                        stopAndRestart();
                    }
                }
                // 加入房间按钮
                if (buttonFlash(e, state == SELECT_ROOM, joinB)) {
                    try {
                        String tmp = JOptionPane.showInputDialog("请输入你要加入的房间号(1~10):");
                        while (tmp != null && (Integer.parseInt(tmp) > 10 || Integer.parseInt(tmp) < 0)) {
                            tmp = JOptionPane.showInputDialog("输入有误,请输入正确范围内的房间号(1~10):");
                        }
                        if (tmp != null && !"".equals(tmp)) {
                            serverPrinter.println("Y");
                            serverPrinter.println(tmp);
                            tmpMsg = serverReader.readLine();
                            if ("ERROR".equals(tmpMsg)) {
                                JOptionPane.showMessageDialog(null, "房间不存在或者房间人数已满!", "进入房间错误",
                                        JOptionPane.ERROR_MESSAGE);
                            } else {
                                roomNum = Integer.parseInt(tmp);
                                frame.setTitle("局域网斗地主:" + name + ":第" + roomNum + "桌");
                                state = IN_ROOM;
                            }
                        }
                    } catch (SocketException socketException) {
                        stopAndRestart();
                    } catch (Exception e1) {
                        e1.printStackTrace();
                    }
                }
                // 创建房间按钮,自动分配房间号
                if (buttonFlash(e, state == SELECT_ROOM, createB)) {
                    try {
                        serverPrinter.println("N");
                        tmpMsg = serverReader.readLine();
                        roomNum = Integer.parseInt(tmpMsg);
                        frame.setTitle("局域网斗地主:" + name + ":第" + (roomNum + 1) + "桌");
                        state = IN_ROOM;
                    } catch (SocketException socketException) {
                        stopAndRestart();
                    } catch (Exception e1) {
                        e1.printStackTrace();
                    }
                }
                // 判断是否点到牌面上
                for (int i = 0; i < myCards.length - 1; i++) {
                    if (state == GAME && e.getX() >= myCards[i].x && e.getX() <= myCards[i].x + 15
                            && e.getY() >= myCards[i].y && e.getY() <= myCards[i].y + 100) {
                        if (myCards[i].y == 350) {
                            myCards[i].y -= 20;
                        } else {
                            myCards[i].y += 20;
                        }
                        errTips = 0;
                        break;
                    }
                }
                // 判断是否点到了最后一张牌
                if (state == GAME && myCards.length != 0 && e.getX() >= myCards[myCards.length - 1].x
                        && e.getX() <= myCards[myCards.length - 1].x + 70 && e.getY() >= myCards[myCards.length - 1].y
                        && e.getY() <= myCards[myCards.length - 1].y + 100) {
                    if (myCards[myCards.length - 1].y == 350) {
                        myCards[myCards.length - 1].y -= 20;
                    } else {
                        myCards[myCards.length - 1].y += 20;
                    }
                    errTips = 0;
                }
                // 出牌按钮
                if (buttonFlash(e, state == GAME && toDo, showB)) {
                    chooseCard();
                    if (showCards.length != 0) {
                        cardType = checkCards(showCards);
                    } else {
                        cardType = 0;
                    }
                    // 比较过程:先比较牌的类型(炸弹等),在比较牌的数量
                    if (cardType != 0) {
                        if (!showPass) {
                            putMyCards();
                        } else if (cardType == nowCardType && showCards.length == nowLen
                                && showCards[0].num > nowCards[0].num) {
                            putMyCards();
                            if (cardType == BOMB || cardType == KINGBOMB) {
                                point *= 2;
                            }
                        } else if ((cardType == BOMB && nowCardType != BOMB && nowCardType != KINGBOMB)
                                || cardType == KINGBOMB) {
                            putMyCards();
                            point *= 2;
                        } else {
                            showCards = new Card[0];
                            errTips = 1;
                        }
                    } else if (showCards.length != 0) {
                        showCards = new Card[0];
                        errTips = 2;
                    }
                }
                // 放下按钮
                if (buttonFlash(e, state == GAME && toDo, putDownB)) {
                    if (tips.size() == 0) {
                        clearChoose();
                        errTips = 3;
                    } else {
                        showTips();
                        errTips = 0;
                    }
                }
                // 不出按钮
                if (buttonFlash(e, state == GAME && toDo && showPass, passB)) {
                    autoPass();
                }
                // 抢地主按钮
                if (buttonFlash(e, state == GAME && toRob, robB)) {
                    serverPrinter.println("Y");
                    isRob = 2;
                    toRob = false;
                    point *= 2;
                    timeTik3.flag = false;
                }
                // 不抢按钮
                if (buttonFlash(e, state == GAME && toRob, noRobB)) {
                    autoPass();
                }
                // 托管按钮
                if (buttonFlash(e, state == GAME && (toRob || toDo), autoB)) {
                    autoPass();
                    toPass = true;
                }
                // 取消托管
                if (buttonFlash(e, state == GAME && toPass, cancelAutoB)) {
                    toPass = false;
                }
            }

            /**
             * 在移动鼠标时,显示按钮的动画效果,在鼠标点击时判断是否在该按钮范围内.
             *
             * @param e
             *            鼠标指针
             * @param flag
             *            判断条件
             * @param b
             *            按钮对象
             * @return 布尔型, 判断是否在该按钮范围内
             */
            public boolean buttonFlash(MouseEvent e, boolean flag, Button b) {
                boolean c = false;
                if (flag && e.getX() > b.getX() && e.getY() > b.getY() && e.getX() < b.getX() + b.getWidth()
                        && e.getY() < b.getY() + b.getHeight()) {
                    b.image = button2;
                    repaint(b.getX(), b.getY(), b.getWidth(), b.getHeight());
                    c = true;
                } else if (flag) {
                    b.image = button1;
                    repaint(b.getX(), b.getY(), b.getWidth(), b.getHeight());
                }
                return c;
            }

            @Override
            public void mouseMoved(MouseEvent e) {
                // 各种按钮动画效果
                buttonFlash(e, state == START, startB);
                buttonFlash(e, state == SELECT_ROOM, joinB);
                buttonFlash(e, state == SELECT_ROOM, createB);
                buttonFlash(e, state == IN_ROOM, exitB);
                buttonFlash(e, state == IN_ROOM, readyB);
                buttonFlash(e, state == GAME && toRob, robB);
                buttonFlash(e, state == GAME && toRob, noRobB);
                buttonFlash(e, state == GAME && toDo, showB);
                buttonFlash(e, state == GAME && toDo, putDownB);
                buttonFlash(e, state == GAME && toDo && showPass, passB);
                buttonFlash(e, state == WAIT, noReadyB);
                buttonFlash(e, state == OVER, goOnB);
                buttonFlash(e, state == OVER, exitRoomB);
                buttonFlash(e, state == GAME && (toRob || toDo), autoB);
                buttonFlash(e, state == GAME && toPass, cancelAutoB);
            }

        };
        this.addMouseMotionListener(m);
        this.addMouseListener(m);

        KeyAdapter k = new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent e) {
                if (e.getKeyCode() == KeyEvent.VK_K) {
                    key = !key;
                }
            }
        };
        this.addKeyListener(k);
        this.setFocusable(true);
        this.requestFocus();
    }

    public static void main(String[] args) {
        frame = new JFrame("局域网斗地主");
        frame.setSize(WIDTH, HEIGHT);
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        frame.setResizable(false);
        frame.setLocationRelativeTo(null);
        frame.add(game);
        frame.setVisible(true);
        game.action();
    }

    /**
     * 服务器信息处理线程,随时接受服务器传来的信息以处理房间状态和游戏状态
     *
     * @author String
     */
    private class ServerHandler extends Thread {
        //volatile修饰符用来保证其它线程读取的总是该变量的最新的值
        private volatile boolean exit = false;

        public void exit() {
            this.exit = true;
        }

        @Override
        public void run() {
            try {
                while (!exit) {
                    Thread.sleep(100);// 防止产生死循环
                    // 等待和房间内状态的服务器信息分类处理
                    if (state == WAIT || state == IN_ROOM || state == OVER || state == GAME) {
                        tmpMsg = serverReader.readLine();
                        if ("ALIVE".equals(tmpMsg) && state == WAIT) {
                            serverPrinter.println("ALIVE");
                        } else {
                            System.out.println("tmpMsg=" + tmpMsg);
                        }
                        if ("ID".equals(tmpMsg)) {
                            myId = Integer.parseInt(serverReader.readLine());
                        }
                        if ("IN".equals(tmpMsg)) {
                            String name = serverReader.readLine();
                            int id = Integer.parseInt(serverReader.readLine());
                            int isReady = Integer.parseInt(serverReader.readLine());
                            if (pl == null) {
                                pl = new Player(name, id, isReady);
                            } else {
                                pr = new Player(name, id, isReady);
                            }

                        }
                        // 接收玩家退出房间的信号
                        if ("OUT".equals(tmpMsg)) {
                            int id = Integer.parseInt(serverReader.readLine());
                            if (pl != null && pl.playerID == id) {
                                pl = null;
                            } else if (pr != null && pr.playerID == id) {
                                pr = null;
                            }

                        }
                        // 接收玩家准备信号
                        if ("READY".equals(tmpMsg)) {
                            int id = Integer.parseInt(serverReader.readLine());
                            if (pl != null && pl.playerID == id) {
                                pl.ready = 1;
                            } else if (pr != null && pr.playerID == id) {
                                pr.ready = 1;
                            }

                        }
                        // 接收取消准备信号
                        if ("CANCELREADY".equals(tmpMsg)) {
                            int id = Integer.parseInt(serverReader.readLine());
                            if (pl != null && pl.playerID == id) {
                                pl.ready = 0;
                            } else if (pr != null && pr.playerID == id) {
                                pr.ready = 0;
                            }

                        }
                        // 接收游戏开始信号
                        if ("START".equals(tmpMsg)) {
                            state = GAME;
                        }

                        // 接受服务器发的牌
                        if ("GIVECARDS".equals(tmpMsg)) {
                            newData();
                            point = 3;
                            getCards();
                            cardSort(myCards);
                            serverPrinter.println("OVER");
                        }
                        // 接收自己抢地主信号
                        if ("TOROB".equals(tmpMsg)) {
                            if (!toPass) {
                                toRob = true;
                                timeTik3.setMax(ROB_TIME);
                                exec.execute(timeTik3);
                            } else {
                                toRob = true;
                                autoPass();
                            }
                        }
                        // 接收谁在抢地主的信号
                        if ("WHOROB".equals(tmpMsg)) {
                            int id = Integer.parseInt(serverReader.readLine());
                            if (pl != null && pl.playerID == id) {
                                pl.isDo = true;
                                timeTik1.setMax(ROB_TIME);
                                exec.execute(timeTik1);
                            } else if (pr != null && pr.playerID == id) {
                                pr.isDo = true;
                                timeTik2.setMax(ROB_TIME);
                                exec.execute(timeTik2);
                            }
                            tmpMsg = serverReader.readLine();
                            if ("Y".equals(tmpMsg)) {
                                if (pl != null && pl.playerID == id) {
                                    pl.isRob = 2;
                                    pl.isDo = false;
                                    timeTik1.flag = false;
                                } else if (pr != null && pr.playerID == id) {
                                    pr.isRob = 2;
                                    pr.isDo = false;
                                    timeTik2.flag = false;
                                }
                                point *= 2;
                            } else {
                                if (pl != null && pl.playerID == id) {
                                    pl.isRob = 1;
                                    pl.isDo = false;
                                    timeTik1.flag = false;
                                } else if (pr != null && pr.playerID == id) {
                                    pr.isRob = 1;
                                    pr.isDo = false;
                                    timeTik2.flag = false;
                                }
                            }
                        }
                        // 接收已选出地主的信号
                        if ("LORD".equals(tmpMsg)) {
                            int id = Integer.parseInt(serverReader.readLine());
                            if (id == myId) {
                                isLord = true;
                                for (int i = 0; i < lordCards.length; i++) {
                                    myCards = Arrays.copyOf(myCards, myCards.length + 1);
                                    myCards[myCards.length - 1] = new Card(250 + (myCards.length - 1) * 15, 350);
                                    myCards[myCards.length - 1].image = lordCards[i].image;
                                    myCards[myCards.length - 1].num = lordCards[i].num;
                                    noteCards[lordCards[i].num]--;
                                    myCards[myCards.length - 1].cardIndex = lordCards[i].cardIndex;
                                    myCards[myCards.length - 1].y = 330;
                                }
                                cardSort(myCards);
                            } else if (pl != null && pl.playerID == id) {
                                pl.isLord = true;
                                pl.cardsNum += 3;
                            } else if (pr != null && pr.playerID == id) {
                                pr.isLord = true;
                                pr.cardsNum += 3;
                            }
                            robIsOver = true;
                        }
                        // 接收谁在出牌的信号
                        if ("WHODO".equals(tmpMsg)) {
                            int id = Integer.parseInt(serverReader.readLine());
                            if (id == myId) {
                                tips.clear();
                                findTips(0, 0);
                                if (!toPass) {
                                    if (pl.isPass && pr.isPass) {
                                        pl.isPass = false;
                                        pr.isPass = false;
                                        showPass = false;
                                    } else {
                                        showPass = true;
                                    }
                                    timeTik3.setMax(SHOW_TIME);
                                    exec.execute(timeTik3);
                                    toDo = true;
                                    isPass = false;
                                    showCards = new Card[0];
                                    times++;
                                } else {
                                    if (pl.isPass && pr.isPass) {
                                        pl.isPass = false;
                                        pr.isPass = false;
                                        showPass = false;
                                    } else {
                                        showPass = true;
                                    }
                                    toDo = true;
                                    showCards = new Card[0];
                                    times++;
                                    autoPass();
                                }
                            } else if (pl != null && pl.playerID == id) {
                                pl.isDo = true;
                                pl.isPass = false;
                                if (isPass && pr.isPass || times == 0) {
                                    isPass = false;
                                    pr.isPass = false;
                                }
                                timeTik1.setMax(SHOW_TIME);
                                exec.execute(timeTik1);
                                // 接收左家出的卡牌
                                pl.cards = new Card[0];

                                String msg = serverReader.readLine();
                                if ("SHOW".equals(msg)) {
                                    nowLen = Integer.parseInt(serverReader.readLine());
                                    nowCardType = Integer.parseInt(serverReader.readLine());
                                    pl.isPass = false;
                                    for (int i = 0; i < nowLen; i++) {
                                        int index = Integer.parseInt(serverReader.readLine());
                                        if (index == -1) {
                                            pl.isWin = true;
                                            score();
                                            state = OVER;
                                            pl.ready = 0;
                                            pr.ready = 0;
                                            break;
                                        }
                                        pl.cardsNum--;
                                        pl.cards = Arrays.copyOf(pl.cards, pl.cards.length + 1);
                                        pl.cards[i] = new Card(100 + i * 15, 120);
                                        pl.cards[i].image = totalCards[index].image;
                                        pl.cards[i].num = totalCards[index].num;
                                        noteCards[pl.cards[i].num]--;
                                    }
                                    nowCards = pl.cards;
                                    pl.isDo = false;
                                } else {
                                    nowLen = Integer.parseInt(serverReader.readLine());
                                    nowCardType = Integer.parseInt(serverReader.readLine());
                                    pl.isPass = true;
                                    pl.isDo = false;
                                }
                                timeTik1.flag = false;
                            } else if (pr != null && pr.playerID == id) {
                                pr.isDo = true;
                                pr.isPass = false;
                                if (isPass && pl.isPass || times == 0) {
                                    isPass = false;
                                    pl.isPass = false;
                                }
                                timeTik2.setMax(SHOW_TIME);
                                exec.execute(timeTik2);
                                // 接收右家出的卡牌
                                pr.cards = new Card[0];

                                String msg = serverReader.readLine();
                                if ("SHOW".equals(msg)) {
                                    nowLen = Integer.parseInt(serverReader.readLine());
                                    nowCardType = Integer.parseInt(serverReader.readLine());
                                    pr.isPass = false;
                                    for (int i = 0; i < nowLen; i++) {
                                        int index = Integer.parseInt(serverReader.readLine());
                                        if (index == -1) {
                                            pr.isWin = true;
                                            score();
                                            state = OVER;
                                            pl.ready = 0;
                                            pr.ready = 0;
                                            break;
                                        }
                                        pr.cardsNum--;
                                        pr.cards = Arrays.copyOf(pr.cards, pr.cards.length + 1);
                                        pr.cards[i] = new Card(600 - (nowLen - i - 1) * 15, 120);
                                        pr.cards[i].image = totalCards[index].image;
                                        pr.cards[i].num = totalCards[index].num;
                                        noteCards[pr.cards[i].num]--;
                                    }
                                    nowCards = pr.cards;
                                    pr.isDo = false;
                                } else {
                                    nowLen = Integer.parseInt(serverReader.readLine());
                                    nowCardType = Integer.parseInt(serverReader.readLine());
                                    pr.isPass = true;
                                    pr.isDo = false;
                                }
                                timeTik2.flag = false;
                            }
                        }
                    }
                }
            } catch (SocketException socketException) {
                stopAndRestart();
            } catch (Exception e) {
                // 如果出错跳出线程,则显示失去连接,并关闭客户端
                e.printStackTrace();
                stopAndRestart();
            } finally {
                stopSocket();
            }
        }
    }
}
